#pragma once

#include "ClassifierTemplateParameter.h"

#include "Classifier.h"

namespace uml {

const bool ClassifierTemplateParameter::allowSubstitutable_default_ = true;
ClassifierTemplateParameter::ClassifierTemplateParameter(const QString& umlType)
    : TemplateParameter(umlType) {}

void ClassifierTemplateParameter::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    TemplateParameter::fromJson(json, errorList);
    allowSubstitutable_ = json.value("allowSubstitutable").toBool(allowSubstitutable_default_);
    JsonSerializable::fromJsonArray(constrainingClassifiers_, "constrainingClassifiers", json, errorList);
    parameteredElement_ = JsonSerializable::create<Classifier>(json.value("parameteredElement"), errorList);

}

void ClassifierTemplateParameter::toJson(QJsonObject& json) {
    TemplateParameter::toJson(json);
    if (allowSubstitutable_ != allowSubstitutable_default_) {
        json.insert("allowSubstitutable", allowSubstitutable_);
    }
    JsonSerializable::toJsonArray(constrainingClassifiers_, "constrainingClassifiers", json);
    if (parameteredElement_) {
        QJsonObject parameteredElement_json;
        parameteredElement_->toJson(parameteredElement_json);
        json.insert("parameteredElement", parameteredElement_json);
    }
}

/// <summary>
/// allowSubstitutable getter
/// Constrains the required relationship between an actual parameter and the
/// parameteredElement for this formal parameter.
/// </summary>
bool ClassifierTemplateParameter::allowSubstitutable() const {
    return allowSubstitutable_;
}

/// <summary>
/// allowSubstitutable setter
/// Constrains the required relationship between an actual parameter and the
/// parameteredElement for this formal parameter.
/// </summary>
void ClassifierTemplateParameter::setAllowSubstitutable(bool value) {
    allowSubstitutable_ = value;
}

/// <summary>
/// constrainingClassifiers getter
/// The classifiers that constrain the argument that can be used for the parameter.
/// If the allowSubstitutable attribute is true, then any Classifier that is
/// compatible with this constraining Classifier can be substituted; otherwise, it
/// must be either this Classifier or one of its specializations. If this property
/// is empty, there are no constraints on the Classifier that can be used as an
/// argument.
/// </summary>
vector<shared_ptr<Classifier>>& ClassifierTemplateParameter::constrainingClassifiers() {
    return constrainingClassifiers_;
}

/// <summary>
/// parameteredElement getter
/// The Classifier exposed by this ClassifierTemplateParameter.
/// </summary>
shared_ptr<Classifier> ClassifierTemplateParameter::parameteredElement() const {
    return parameteredElement_;
}

/// <summary>
/// parameteredElement setter
/// The Classifier exposed by this ClassifierTemplateParameter.
/// </summary>
void ClassifierTemplateParameter::setParameteredElement(shared_ptr<Classifier> value) {
    parameteredElement_ = value;
}

} // namespace uml
